# -*- coding: utf-8 -*-
#
# $AIST_Release: 0.9.0 $
# Copyright 2011 Information Technology Research Institute, National
# Institute of Advanced Industrial Science and Technology
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#    http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Module for array-like file reader"""

class FileBuffer:
    """ Array-like file reader """

    BUFFER_SIZE = 32 * 1024

    def __init__(self, filename):
        self.fp      = open(filename)
        self.buffers = []

    def __getitem__(self, key):
        idx = 0
        if isinstance(key, slice):
            assert key.step == None or key.step == 1
            assert key.start <= key.stop

            f = key.start
            l = key.stop

            idx = l / FileBuffer.BUFFER_SIZE
            self._read(idx + 1)

            i = f / FileBuffer.BUFFER_SIZE

            if i == idx:
                return self.buffers[idx][f % FileBuffer.BUFFER_SIZE:l % FileBuffer.BUFFER_SIZE]
            else:
                b = self.buffers[i][f % FileBuffer.BUFFER_SIZE:]
                for j in xrange(i + 1, idx):
                    b += self.buffers[j]
                return b + self.buffers[idx][:l % FileBuffer.BUFFER_SIZE]
        else:
            idx = key / FileBuffer.BUFFER_SIZE
            self._read(idx + 1)

            return self.buffers[idx][key % FileBuffer.BUFFER_SIZE]

    def __len__(self):
        self._read(2) # current and next

        l = 0
        for b in self.buffers:
            l += len(b)

        return l

    def drop(self, pos):
        n = pos / FileBuffer.BUFFER_SIZE

        self.buffers = self.buffers[n:]

        return pos % FileBuffer.BUFFER_SIZE

    def close(self):
        self.fp.close()

    def _read(self, n):
        while len(self.buffers) < n:
            b = self.fp.read(FileBuffer.BUFFER_SIZE)
            self.buffers.append(b)
            if len(b) < FileBuffer.BUFFER_SIZE:
                break

